#pragma once

#include <cstdint>
#include <string>

/* 服务器端发送往客户端的消息类型 */
enum message_type_server_to_client {
    MSG_TYPE_S2C_HEARTBEAT = 0,
    MSG_TYPE_S2C_USER_LOGIN,
    MSG_TYPE_S2C_USER_REGISTER,

    MSG_TYPE_S2C_START_MATCHING,
    MSG_TYPE_S2C_STOP_MATCHING,

    MSG_TYPE_S2C_LEFT_BUTTON_CLICKED,

    MSG_TYPE_S2C_GAME_INIT,
    MSG_TYPE_S2C_GAME_OVER,
    MSG_TYPE_S2C_MAX
};

/* 客户端发送往服务器端的消息类型 */
enum message_type_client_to_server {
    MSG_TYPE_C2S_HEARTBEAT = 0,
    MSG_TYPE_C2S_USER_LOGIN,
    MSG_TYPE_C2S_USER_REGISTER,

    MSG_TYPE_C2S_START_MATCHING,
    MSG_TYPE_C2S_STOP_MATCHING,

    MSG_TYPE_C2S_LEFT_BUTTON_CLICKED,
    MSG_TYPE_C2S_MAX
};

struct message_header {
    uint32_t msg_type_; /* @ref: message_type_server_to_client, message_type_client_to_server */
    uint16_t msg_size_; /* 消息内容的大小，不包含消息头 */
    uint16_t checksum_; /* 对消息内容逐字节累加 */
};

#define NET_MESSAGE_HEADER_SIZE (sizeof(message_header))

#define NET_MESSAGE_BODY_MAX_SIZE   1024

/* 定义网络消息类型为64bit消息头 + 消息内容，消息内容为protobuf序列化号的字符串 */
struct network_message {
    message_header header_;
    std::string data_;      /* protobuf序列化后的字符串 */

    network_message() = default;
    network_message(uint32_t msg_type, const std::string& data) : data_(data)
    {
        header_.msg_type_ = msg_type;
        header_.msg_size_ = data.size();
        header_.checksum_ = caculate_checksum();
    }

    auto to_string() const
    {
        std::string str(reinterpret_cast<const char *>(&header_), NET_MESSAGE_HEADER_SIZE);
        str.append(data_);
        return str;
    }

    uint16_t caculate_checksum() const
    {
        uint16_t sum = 0;
        for (int i = 0; i < data_.size(); ++i) {
            sum += data_[i];
        }
        return sum;
    }
};
